/*
 * brin_page.h
 *		BRIN 页面布局的原型和定义
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
 *		src/include/access/brin_page.h
 *
 * NOTES
 *
 * 这些结构实际上应该仅限于特定的 BRIN 文件，但将它们放在这里
 * 可以方便 pageinspect 和类似工具使用。
 */
#ifndef BRIN_PAGE_H
#define BRIN_PAGE_H

#include "storage/block.h"
#include "storage/itemptr.h"

/*
 * BRIN 页面特殊区域。
 *
 * 我们以这种奇怪的方式定义它，以便它始终占据每个页面的最后
 * MAXALIGN 大小的元素。
 */
typedef struct BrinSpecialSpace
{
	uint16		vector[MAXALIGN(1) / sizeof(uint16)];
} BrinSpecialSpace;

/*
 * 使页面类型成为页面中的最后半字，用于 pg_filedump
 * 和类似工具的使用。我们实际上不太关心 "flags" 半字的位置，
 * 但对两者应用一致规则会更简单。
 *
 * 请参阅 GinPageOpaqueData 上面的注释。
 */
#define BrinPageType(page)		\
	(((BrinSpecialSpace *)		\
	  PageGetSpecialPointer(page))->vector[MAXALIGN(1) / sizeof(uint16) - 1])

#define BrinPageFlags(page)		\
	(((BrinSpecialSpace *)		\
	  PageGetSpecialPointer(page))->vector[MAXALIGN(1) / sizeof(uint16) - 2])

/* 所有 BRIN 页面上的特殊空间存储 "类型" 标识符 */
#define		BRIN_PAGETYPE_META			0xF091
#define		BRIN_PAGETYPE_REVMAP		0xF092
#define		BRIN_PAGETYPE_REGULAR		0xF093

#define BRIN_IS_META_PAGE(page) (BrinPageType(page) == BRIN_PAGETYPE_META)
#define BRIN_IS_REVMAP_PAGE(page) (BrinPageType(page) == BRIN_PAGETYPE_REVMAP)
#define BRIN_IS_REGULAR_PAGE(page) (BrinPageType(page) == BRIN_PAGETYPE_REGULAR)

/* BrinSpecialSpace 的标志 */
#define		BRIN_EVACUATE_PAGE			(1 << 0)


/* 元数据页面定义 */
typedef struct BrinMetaPageData
{
	uint32		brinMagic;
	uint32		brinVersion;
	BlockNumber pagesPerRange;
	BlockNumber lastRevmapPage;
} BrinMetaPageData;

#define BRIN_CURRENT_VERSION		1
#define BRIN_META_MAGIC			0xA8109CFA

#define BRIN_METAPAGE_BLKNO		0

/* revmap 页的定义 */
typedef struct RevmapContents
{
	/*
	 * 该数组将填充页面上所有可用的空间。它应该被声明为 [FLEXIBLE_ARRAY_MEMBER]，
	 * 但出于某种原因，你不能在其他空的结构中这样做。
	 */
	ItemPointerData rm_tids[1];
} RevmapContents;

#define REVMAP_CONTENT_SIZE \
	(BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - \
	 offsetof(RevmapContents, rm_tids) - \
	 MAXALIGN(sizeof(BrinSpecialSpace)))
/* 数组中项目的最大数量 */
#define REVMAP_PAGE_MAXITEMS \
	(REVMAP_CONTENT_SIZE / sizeof(ItemPointerData))

#endif							/* BRIN_PAGE_H */
